let activeEffect = undefined;
// const effect = (fn) => {
//   activeEffect = fn;
//   fn();
// };

const bucket = new WeakMap();
// 追踪
const track = (target, key) => {
  if (!activeEffect) return;

  let depsMap = bucket.get(target); // WeakMap 由 target --> Map 构成；
  if (!depsMap) {
    bucket.set(target, (depsMap = new Map()));
  }
  let deps = depsMap.get(key); // Map 由 key --> Set 构成
  if (!deps) {
    depsMap.set(key, (deps = new Set()));
  }
  // 最后将当前激活的副作用函数添加到桶中
  deps.add(activeEffect);

  // deps就是一个与当前副作用函数存在关联的依赖集合
  activeEffect.deps.push(deps);
  // console.log(888, depsMap);
  // console.log(999, activeEffect.deps);
};
// 触发
const trigger = (target, key) => {
  let depsMap = bucket.get(target);
  if (!depsMap) return;
  let deps = depsMap.get(key);
  // 执行副作用函数
  const effectSet = new Set(deps);
  // console.log("trigger==", key, effectSet);
  effectSet && effectSet.forEach((fn) => fn());
};

// 4.5 嵌套的effect和effect栈
// 要解决的问题：一个响应式数据只会收集直接读取其值的副作用函数，而不会出现互相影响的情况。
// 定义一个栈来存储副作用函数
const effectStack = [];
const effect = (fn) => {
  const _effectFn = () => {
    cleanup(_effectFn);
    activeEffect = _effectFn;
    // 将当前副作用函数压入栈中
    effectStack.push(_effectFn);
    fn();
    // 副作用函数执行完之后 将其从栈中弹出
    effectStack.pop();
    // activeEffect始终指向栈顶的副作用函数
    activeEffect = effectStack[effectStack.length - 1];
  };
  //  用来存储 所有与当前副作用函数相关联的依赖集合
  _effectFn.deps = [];

  _effectFn();
};

const cleanup = (effectFn) => {
  for (let i = 0; i < effectFn.deps.length; i++) {
    const deps = effectFn.deps[i];
    deps.delete(effectFn);
  }
  effectFn.deps.length = 0;
};

// 测试代码
const data = {
  foo: true,
  bar: true,
};
const obj = new Proxy(data, {
  get(target, key) {
    track(target, key);
    return target[key];
  },
  set(target, key, val) {
    target[key] = val;
    trigger(target, key);
    return true;
  },
});

let temp1, temp2;
effect(function effectF1() {
  console.log("effectF1执行===");
  effect(function effectF2() {
    console.log("effectF2执行===");
    temp2 = obj.bar;
  });
  temp1 = obj.foo;
});

setTimeout(() => {
  console.log("2s之后===");
  // obj.foo = false;
  obj.bar = false;
});
// 通过effectStack副作用函数栈，能保证修改obj.foo时 触发effectF1、effectF2
// 修改obj.bar时，只触发effectF2
